package com.heima.media.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.client.ArticleClient;
import com.heima.common.dto.ResponseResult;
import com.heima.domain.ArticleDto;
import com.heima.media.aliyun.GreenImageScan;
import com.heima.media.aliyun.GreenTextScan;
import com.heima.media.dto.ContentDto;
import com.heima.media.dto.ImageDto;
import com.heima.media.entity.WmChannel;
import com.heima.media.entity.WmNews;
import com.heima.media.entity.WmUser;
import com.heima.media.service.IAuditService;
import com.heima.media.service.IWmChannelService;
import com.heima.media.service.IWmNewsService;
import com.heima.media.service.IWmUserService;
import com.heima.minio.MinIOTemplate;
import org.apache.commons.io.IOUtils;
import org.redisson.api.RBlockingDeque;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class AuditServiceImpl implements IAuditService {

    @Autowired
    private GreenTextScan greenTextScan;

    @Autowired
    private IWmNewsService wmNewsService;

    @Autowired
    private MinIOTemplate minIOTemplate;

    @Autowired
    private GreenImageScan greenImageScan;

    @Autowired
    private ArticleClient articleClient;

    @Autowired
    private IWmUserService wmUserService;

    @Autowired
    private IWmChannelService wmChannelService;

    @Autowired
    private RedissonClient redissonClient;

    @Override
    @Async//异步方法调用
    public void audit(WmNews wmNews) {
        //文本审核
        boolean flag = checkText(wmNews);
        if (!flag) return;

        //图片审核
        flag = checkImages(wmNews);
        if (!flag) return;

        //还需要判断是否到达发布时间
        if (new Date().getTime() > wmNews.getPublishTime().getTime()) {
            //达到发布时间
            Long articleId = createApArticle(wmNews);
            wmNews.setArticleId(articleId);
            wmNews.setStatus(9);
            wmNewsService.updateById(wmNews);
        } else {
            //没有达到发布时间
            wmNews.setStatus(8);
            wmNewsService.updateById(wmNews);

            //放入到延迟队列
            RBlockingDeque<Integer> rBlockingDeque = redissonClient.getBlockingDeque("publish-article-queue");
            RDelayedQueue<Integer> delayedQueue = redissonClient.getDelayedQueue(rBlockingDeque);
            //计算延迟时间
            long time = wmNews.getPublishTime().getTime() - System.currentTimeMillis();
            delayedQueue.offer(wmNews.getId(), time, TimeUnit.MILLISECONDS);//注意时间单位:毫秒
        }
    }

    public Long createApArticle(WmNews wmNews) {
        WmUser wmUser = wmUserService.getById(wmNews.getUserId());

        ArticleDto articleDto = new ArticleDto();
        articleDto.setContent(wmNews.getContent());
        articleDto.setTitle(wmNews.getTitle());
        articleDto.setAuthorId(wmUser.getApAuthorId());
        articleDto.setAuthorName(wmUser.getName());
        articleDto.setChannelId(wmNews.getChannelId());

        WmChannel wmChannel = wmChannelService.getById(wmNews.getChannelId());

        articleDto.setChannelName(wmChannel.getName());
        articleDto.setLayout(wmNews.getType());
        articleDto.setFlag(0);

        List<String> urlList = new ArrayList<>();
        List<ImageDto> imageDtoList = JSON.parseArray(wmNews.getImages(), ImageDto.class);
        for (ImageDto imageDto : imageDtoList) {
            urlList.add(imageDto.getUrl());
        }
        articleDto.setImages(String.join(",", urlList)); //用逗号分隔每个url

        articleDto.setLabels(wmNews.getLabels());
        articleDto.setPublishTime(wmNews.getPublishTime());
        ResponseResult<Long> responseResult = articleClient.saveArticle(articleDto);
        return responseResult.getData();
    }

    //图片审核
    private boolean checkImages(WmNews wmNews) {
        //图片有两种：内容图片+封面图片
        List<String> allUrlList = new ArrayList<>();

        //获取内容图片
        List<ContentDto> contentDtoList = JSON.parseArray(wmNews.getContent(), ContentDto.class);
        for (ContentDto contentDto : contentDtoList) {
            if (contentDto.getType().equals("image")) {
                allUrlList.add(contentDto.getValue());
            }
        }

        String images = wmNews.getImages();
        List<ImageDto> imageDtoList = JSON.parseArray(images, ImageDto.class);
        for (ImageDto imageDto : imageDtoList) {
            if (!allUrlList.contains(imageDto.getUrl())) {
                allUrlList.add(imageDto.getUrl());
            }
        }
        //要从minio中下载图片
        try {
            List<byte[]> byteList = new ArrayList<>();
            for (String url : allUrlList) {
                InputStream inputStream = minIOTemplate.download(url);
                byte[] bytes = IOUtils.toByteArray(inputStream);
                byteList.add(bytes);
            }
            Map map = greenImageScan.imageScan(byteList);
            String suggestion = (String) map.get("suggestion");
            switch (suggestion) {
                case "pass": {
                    return true;
                }
                case "review": {
                    String reason = (String) map.get("label"); //不通过时map有两对数据
                    wmNews.setStatus(3); //需要人工审核
                    wmNews.setReason("图片需要人工审核，图片审核不通过的原因是：" + reason);
                    wmNewsService.updateById(wmNews);
                    return false;
                }
                case "block": {
                    String reason = (String) map.get("label"); //不通过时map有两对数据
                    wmNews.setStatus(2); //需要人工审核
                    wmNews.setReason("图片审核审核失败的原因是是：" + reason);
                    wmNewsService.updateById(wmNews);
                    return false;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    //文本审核
    private boolean checkText(WmNews wmNews) {
        //文本=标题+文章内容
        String text = wmNews.getTitle();

        List<ContentDto> contentDtoList = JSON.parseArray(wmNews.getContent(), ContentDto.class);
        for (ContentDto contentDto : contentDtoList) {
            if (contentDto.getType().equals("text")) {
                text += contentDto.getValue();
            }
        }

        try {
            Map map = greenTextScan.greenTextScan(text);
            String suggestion = (String) map.get("suggestion");
            switch (suggestion) {
                case "pass": {
                    return true;
                }
                case "review": {
                    String reason = (String) map.get("label"); //不通过时map有两对数据
                    wmNews.setStatus(3); //需要人工审核
                    wmNews.setReason("文本需要人工审核，文本审核不通过的原因是：" + reason);
                    wmNewsService.updateById(wmNews);
                    return false;
                }
                case "block": {
                    String reason = (String) map.get("label"); //不通过时map有两对数据
                    wmNews.setStatus(2); //需要人工审核
                    wmNews.setReason("文本审核审核失败的原因是是：" + reason);
                    wmNewsService.updateById(wmNews);
                    return false;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}